package com.wh1200.mybatis.xmlless.config

import com.wh1200.mybatis.xmlless.JavaClassWrapper
import com.wh1200.mybatis.xmlless.XmlLessMapper
import com.wh1200.mybatis.xmlless.methods.XmlLessMethods
import com.wh1200.mybatis.xmlless.util.TableInfoProvider
import com.baomidou.mybatisplus.core.injector.AbstractMethod
import com.baomidou.mybatisplus.core.injector.AbstractSqlInjector
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector
import com.baomidou.mybatisplus.core.metadata.TableInfo
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils
import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit
import org.apache.ibatis.builder.MapperBuilderAssistant


/**
 * SQL注入
 *
 * Created by 吴昊 on 2018/11/6.
 *
 * @author 吴昊
 * @since 0.0.1-SNAPSHOT
 */
class XmllessSqlInjector : AbstractSqlInjector() {

  private val defaultSqlInjector = DefaultSqlInjector()

  override fun inspectInject(builderAssistant: MapperBuilderAssistant, mapperClass: Class<*>?) {
    super.inspectInject(builderAssistant, mapperClass)
    val modelClass = ReflectionKit.getSuperClassGenericType(
        mapperClass, XmlLessMapper::class.java, 0
    )
    if (modelClass == null) {
      return
    }
    TableInfoProvider.getOrInitXmllessTableInfo(
        JavaClassWrapper(modelClass),
        false
    )
    val className = mapperClass.toString()
    val mapperRegistryCache = GlobalConfigUtils.getMapperRegistryCache(
        builderAssistant.configuration
    )
    if (mapperRegistryCache.contains(className)) {
      return
    }
    val tableInfo = TableInfoHelper.initTableInfo(builderAssistant, modelClass)
    val methodList: List<AbstractMethod> = this.getMethodList(mapperClass!!, tableInfo)
    if (CollectionUtils.isNotEmpty(methodList)) {
      // 循环注入自定义方法
      methodList.forEach { m ->
        m.inject(
            builderAssistant,
            mapperClass,
            modelClass,
            tableInfo
        )
      }
    } else {
      logger.debug("$mapperClass, No effective injection method was found.")
    }
    mapperRegistryCache.add(className)
  }

  override fun getMethodList(mapperClass: Class<*>, tableInfo: TableInfo): MutableList<AbstractMethod> {
    val list = arrayListOf<AbstractMethod>()
    val mybatisPlusInjections = defaultSqlInjector.getMethodList(mapperClass, tableInfo)
    list.add(XmlLessMethods())
    list.addAll(mybatisPlusInjections)
    return list
  }

}
